import os
import logging
import re
import typing

from GnToolBox.basic_tool import BasicTool


class GnCommonTool:
    """
    处理BUILD.gn文件的通用方法
    """

    @classmethod
    def find_files(cls, project_path: str,
                   target_filename: str = "BUILD.gn",
                   black_keywords: tuple = tuple(),
                   black_dirs: tuple = tuple()) -> set:
        """
        基于linux的find命令查找文件
        """
        cmd = "find {} -name {}".format(project_path,
                                        target_filename)
        result_set = set()
        for bd in black_dirs:
            cmd += " ! -path \"./{}/*\"".format(bd)
        output = os.popen(cmd)
        for file in output:
            if BasicTool.contains_keywords(file, black_keywords):
                continue
            result_set.add(file.strip())
        logging.info("total: {}".format(len(result_set)))
        return result_set

    @classmethod
    def grep(cls, grep_pattern: str, grep_path: str, exclude: tuple = tuple(),
             black_keyword: tuple = tuple(),
             include="BUILD.gn",
             get_1=False) -> str:
        """
        调用linux的grep命令，开启了通用的正则匹配
        grep_path：可以是路径，也可以是文件
        没有grep到内容，返回None
        """
        cmd = "grep -Ern '{}' {}".format(grep_pattern, grep_path)
        cmd += " --include={}".format(include)
        for e in exclude:
            cmd += " --exclude={}".format(e)
        if len(black_keyword) != 0:
            cmd += " | grep -Ev '{}'".format("|".join(black_keyword))
        if get_1:
            cmd += " | head -n 1"
        logging.info("[grep] cmd: {}".format(cmd))
        result = None
        output = os.popen(cmd).readlines()
        if len(output) != 0:
            result = output
        return result

    @classmethod
    def is_gn_variable(cls, target: str):
        """
        判断target（应是一个=右边的东西）是否是gn中的变量:
        b = "xxx"
        c = b
        c = "${b}"
        """
        target = target.strip()
        if target.startswith('"') and target.endswith('"'):
            target = target.strip('"')
            if target.startswith("${") and target.endswith("}"):
                return True
            return False
        else:
            return True

    # 给__find_variables_in_gn用的，减少io
    __var_val_mem_dict = dict()

    @classmethod
    def find_variables_in_gn(cls, var_name_tuple: tuple, path: str, stop_tail: str = "home") -> tuple:
        """
        同时查找多个gn变量的值
        var_name_tuple：变量名的tuple，变量名应是未经过处理后的，如：
        xxx
        "${xxx}"
        """

        if os.path.isfile(path):
            path = os.path.split(path)[0]
        logging.info("{} are variables, now try to find their value".format(
            ",".join(var_name_tuple)))
        var_val_dict = dict()
        not_found_count = len(var_name_tuple)
        for var in var_name_tuple:
            val = GnCommonTool.__var_val_mem_dict.get(var)
            if val is not None:
                not_found_count -= 1
            var_val_dict[var] = val
        while not path.endswith(stop_tail) and not_found_count != 0:
            for v in var_name_tuple:
                cmd = r"grep -Ern '^( *){} *= *\".*?\"' --include=*.gn* | head -n 1 | grep -E '\".*\"' -wo".format(
                    v.strip('"').lstrip("${").rstrip('}'))
                output = os.popen(cmd).read().strip().strip('"')
                if len(output) != 0:
                    not_found_count -= 1
                    var_val_dict[v] = output
                    GnCommonTool.__var_val_mem_dict[v] = output
            path = os.path.split(path)[0]
        return tuple(var_val_dict.values())

    @classmethod
    def find_paragraph_iter(cls, start_pattern: str, content: str, end_pattern: str = r"\}") \
            -> typing.Iterator[re.Match]:
        """
        匹配以start_pattern开头、end_pattern结尾的代码段
        example: 匹配ohos_shared_library
        iter = GnCommon.find_paragraph_iter(start_pattern="ohos_shared_library", end_pattern="\}", content=content)
        for i in iter:
            print(i.group())
        caution：如果是嵌套内容，则只能匹配外层的，且无法匹配单行内容
        """
        pattern = r"^( *){}[\s|\S]*?\n\1{}$".format(start_pattern, end_pattern)
        ptrn = re.compile(pattern, flags=re.S | re.M)
        result = re.finditer(ptrn, content)
        return result
